package com.doge.service.admin.role;

import com.alibaba.druid.util.StringUtils;
import com.doge.bean.base.BaseData;
import com.doge.bean.base.BaseParam;
import com.doge.bean.pojo.admin.Admin;
import com.doge.bean.pojo.admin.AdminExample;
import com.doge.bean.pojo.log.Log;
import com.doge.bean.pojo.log.LogExample;
import com.doge.bean.pojo.permission.Permission;
import com.doge.bean.pojo.permission.PermissionExample;
import com.doge.bean.pojo.permission.PermissionList;
import com.doge.bean.pojo.permission.PermissionListExample;
import com.doge.bean.pojo.role.Role;
import com.doge.bean.pojo.role.RoleExample;
import com.doge.bean.vo.role.PermissionVO;
import com.doge.bean.vo.role.RoleOptionsVO;
import com.doge.exception.Delete502Exception;
import com.doge.exception.Param602Exception;
import com.doge.mapper.*;
import com.doge.service.admin.storage.StorageService;
import com.doge.util.anno.FuncTimeCount;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.SneakyThrows;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @program: doge
 * @description:
 * @author: Keyu Li
 * @create: 2021-11-29 20:55
 **/

@Service
public class RoleServiceImpl implements RoleService {
    @Autowired
    AdminMapper adminMapper;
    @Autowired
    RoleMapper mapper;
    @Autowired
    PermissionListMapper listMapper;
    @Autowired
    PermissionMapper permMapper;

    @Override
    public BaseData options() {
        // 查询所有的 role
        RoleExample example = new RoleExample();
        List<Role> roles = mapper.selectByExample(example);
        // roles 转换为 RoleOptionsVo 列表
        ArrayList<RoleOptionsVO> optionsVOS = new ArrayList<>();
        for (Role role : roles) {
            RoleOptionsVO vo = new RoleOptionsVO();
            vo.setValue(role.getId());
            vo.setLabel(role.getName());
            optionsVOS.add(vo);
        }
        BaseData data = new BaseData();
        data.setPages(1);
        data.setPage(1);
        data.setLimit(roles.size());
        data.setTotal((long) roles.size());
        data.setList(optionsVOS);
        return data;
    }

    @Override
    public BaseData list(BaseParam param, String name) {
        // 分页
        PageHelper.startPage(param.getPage(), param.getLimit());
        // 模糊查询
        RoleExample example = new RoleExample();
        example.createCriteria().andDeletedEqualTo(false);
        if (!StringUtils.isEmpty(name)) {
            example.createCriteria().andNameLike("%" + name + "%");
        }
        // 获得 List<Log>
        List<Role> roles = mapper.selectByExample(example);
        // 封装返回
        PageInfo pageInfo = new PageInfo(roles);
        BaseData data = BaseData.list(roles, pageInfo.getTotal());
        data.setPages(pageInfo.getPages());
        data.setPage(param.getPage());
        data.setLimit(param.getLimit());
        return data;
    }

    @Override
    public Role create(Role role) throws Exception {
        // 查询 name是否重复
        RoleExample example = new RoleExample();
        example.createCriteria().andNameEqualTo(role.getName());
        long l = mapper.countByExample(example);
        if (l != 0)
            throw new Param602Exception("不能有重复的角色名！");
        // 插入角色，返回 id
        role.setAddTime(new Date());
        role.setUpdateTime(new Date());
        mapper.insertSelective(role);
        return role;
    }

    @Override
    public void update(Role role) throws Exception {
        // 判断是否修改 超级管理员 名称
        if (role.getId() == 1 && !"超级管理员".equals(role.getName()))
            throw new Param602Exception("禁止修改超级超级管理员名称！");
        // 判断 角色名name 是否已经存在(排除自身)
        RoleExample example = new RoleExample();
        example.createCriteria().andNameEqualTo(role.getName()).andIdNotEqualTo(role.getId());
        long l = mapper.countByExample(example);
        if (l != 0)
            throw new Param602Exception("角色名已存在！");
        // 选择更新用户: 只更新不为 null的列
        mapper.updateByPrimaryKeySelective(role);
    }

    @Override
    public void delete(Role role) throws Exception {
        // 判断当前角色是否是超级管理员角色
        if (role.getId() == 1) {
            throw new Param602Exception("禁止删除超级管理员！");
        }
        //判断当前角色没有对应管理员再删除
        //      查询admin表：[id] [id,%  %,id,%  %id]
        //      因为example是使用 and逻辑，因此手写sql
        //      role_ids like '[1]' or role_ids like '[1,%' or role_ids like '%,1,%' or role_ids like '%1]'
        Integer id = role.getId();
        String likeId = "role_ids like '[" + id + "]' or role_ids like '[" + id
                + ",%' or role_ids like '%," + id + ",%' or role_ids like '%" + id + "]'";
        int adminOfRoles = adminMapper.selectAdminNumsByRoleId(likeId);
        if (adminOfRoles != 0) {
            throw new Param602Exception("当前角色存在管理员，不能删除！");
        }
        //根据 id和 name 删除角色（缺一不可！）
        RoleExample example = new RoleExample();
        example.createCriteria().andIdEqualTo(role.getId()).andNameEqualTo(role.getName());
        // 逻辑删除，不是真实的删除
        role.setDeleted(true);
        int i = mapper.updateByExampleSelective(role, example);
        if (i != 1)
            throw new Delete502Exception("删除角色失败！");
    }

    /**
     * 回显，获取全部系统的 权限，及当前角色对应权限
     *
     * @param id:
     * @return com.doge.bean.vo.role.PermissionVO
     * @date 12/3/2021 14:47
     */
    @FuncTimeCount
    @Override
    public PermissionVO getPersmissions(Integer id) {
        // 返回的 vo
        PermissionVO permissionVO = new PermissionVO();
        // 查询 permission_list 得到 PermissionList
        List<PermissionList> sysPerms = listMapper.selectByExample(new PermissionListExample());
        // 将 PermissionList 转换为 PermissionVO.systemPermissions，赋值给vo
        List<PermissionVO.SystemPermission> systemPermissions = parse(sysPerms);
        permissionVO.setSystemPermissions(systemPermissions);

        // 查询 permission表获取当前role对应的权限
        PermissionExample example = new PermissionExample();
        example.createCriteria().andRoleIdEqualTo(id);
        List<Permission> permissions = permMapper.selectByExample(example);
        // 如果当前角色权限是 *，则返回 全部  ----> 不再考虑此情况
//        if (permissions.size() == 1 && "*".equals(permissions.get(0).getPermission())) {
//            permissionVO.setAssignedPermissions(systemPermissions);
//            return permissionVO;
//        }
        // 提取 Permissions 中的 permission
        List<String> permIds = new ArrayList<>();
        for (Permission permission : permissions) {
            permIds.add(permission.getPermission());
        }
        // 不需要转换！！！！
        // 查询 permission_list (也包括父标签) 转换为 PermissionList.assignedPermissions
        //List<PermissionVO.SystemPermission> assignedPermissions = selectAssign(permIds);

        // 赋值为 PermissionVO
        permissionVO.setAssignedPermissions(permIds);
        return permissionVO;
    }

    private List<PermissionVO.SystemPermission> parse(List<PermissionList> perms) {
        List<PermissionVO.SystemPermission> permL1s = new ArrayList<>();
        // 第一级目录赋值：
        for (PermissionList perm1 : perms) {
            if (perm1.getType() == 1) {
                // 第一级目录赋值：
                PermissionVO.SystemPermission permL1 = new PermissionVO.SystemPermission();
                permL1.setId(perm1.getLabel());
                permL1.setLabel(perm1.getLabel());
                // 第二级目录赋值
                List<PermissionVO.SystemPermission.ControllerLabel> permL2s = new ArrayList<>();
                for (PermissionList perm2 : perms) {
                    if (perm2.getType() == 2 && perm2.getPid().equals(perm1.getId())) {
                        PermissionVO.SystemPermission.ControllerLabel permL2 = new PermissionVO.SystemPermission.ControllerLabel();
                        permL2.setId(perm2.getLabel());
                        permL2.setLabel(perm2.getLabel());
                        // 第三级目录赋值
                        List<PermissionVO.SystemPermission.ControllerLabel.FuncLabel> permL3s = new ArrayList<>();
                        for (PermissionList perm3 : perms) {
                            if (perm3.getType() == 3 && perm3.getPid().equals(perm2.getId())) {
                                PermissionVO.SystemPermission.ControllerLabel.FuncLabel permL3 = new PermissionVO.SystemPermission.ControllerLabel.FuncLabel();
                                permL3.setId(perm3.getPermission());
                                permL3.setLabel(perm3.getLabel());
                                permL3.setApi(perm3.getApi());
                                permL3s.add(permL3);
                            }
                        }
                        permL2.setChildren(permL3s);
                        permL2s.add(permL2);
                    }
                }
                permL1.setChildren(permL2s);
                permL1s.add(permL1);
            }
        }
        return permL1s;
    }

    /*
     * 可能为空
     * 白写了！！！日！！！
     * */
    private List<PermissionVO.SystemPermission> selectAssign(List<String> permIds) {
        PermissionListExample example = new PermissionListExample();
        example.createCriteria().andPermissionIn(permIds);
        List<PermissionList> perm3Lists = listMapper.selectByExample(example);
        // 如果什么都没有查到，直接返回空list
        if (perm3Lists.size() == 0) {
            return parse(new ArrayList<PermissionList>());
        }
        // 根据 第3级目录 查询 第2级目录
        HashSet<Integer> pids = new HashSet<>();
        for (PermissionList perm3List : perm3Lists) {
            pids.add(perm3List.getPid());
        }
        example.createCriteria().andIdIn(new ArrayList<>(pids));
        List<PermissionList> perm2Lists = listMapper.selectByExample(example);
        // 根据 第2级目录 查询 第1级目录
        pids.clear();
        for (PermissionList perm2List : perm2Lists) {
            pids.add(perm2List.getPid());
        }
        example.createCriteria().andIdIn(new ArrayList<>(pids));
        List<PermissionList> perm1Lists = listMapper.selectByExample(example);
        // 合并三级目录，使用转换方法转换为 PermissionVO$SystemPermission
        perm1Lists.addAll(perm2Lists);
        perm1Lists.addAll(perm3Lists);
        return parse(perm1Lists);
    }


    /*
     * 只是一个临时使用的方法
     * */
    @FuncTimeCount
    @Override
    public void insertPermissions(PermissionVO perm) {
        // 将 PermissionVO 第一层 转换为 list对象，插入并返回自增主键
        ArrayList<PermissionList> perm1lists = new ArrayList<>();
        List<PermissionVO.SystemPermission> label1s = perm.getSystemPermissions();
        for (PermissionVO.SystemPermission label1 : label1s) {
            PermissionList perm1 = new PermissionList();
            perm1.setPid(0);
            perm1.setType(1);
            perm1.setLabel(label1.getLabel());
            // 插入并返回主键
            listMapper.insertSelective(perm1);
            perm1lists.add(perm1);
        }
        // 将 PermissionVO 第二层 insert 数据库
        List<PermissionVO.SystemPermission.ControllerLabel> label2Alls = new ArrayList<>();
        ArrayList<PermissionList> perm2lists = new ArrayList<>();
        for (int i = 0; i < label1s.size(); i++) {
            List<PermissionVO.SystemPermission.ControllerLabel> label2s = label1s.get(i).getChildren();
            for (PermissionVO.SystemPermission.ControllerLabel label2 : label2s) {
                PermissionList perm2 = new PermissionList();
                perm2.setPid(perm1lists.get(i).getId());
                perm2.setType(2);
                perm2.setLabel(label2.getLabel());
                // 插入并返回主键
                listMapper.insertSelective(perm2);
                perm2lists.add(perm2);
            }
            label2Alls.addAll(label2s);
        }
        // 将 PermissionVO 第三层 insert 数据库
        // 直接遍历 label2Alls, label2Alls 和 perm2lists 是一一对应的
        for (int i = 0; i < label2Alls.size(); i++) {
            List<PermissionVO.SystemPermission.ControllerLabel.FuncLabel> label3s = label2Alls.get(i).getChildren();
            for (PermissionVO.SystemPermission.ControllerLabel.FuncLabel label3 : label3s) {
                PermissionList perm3 = new PermissionList();
                perm3.setPid(perm2lists.get(i).getId());
                perm3.setType(3);
                perm3.setLabel(label3.getLabel());
                perm3.setApi(label3.getApi());
                perm3.setPermission(label3.getId());
                // 插入并返回主键
                listMapper.insertSelective(perm3);
            }
        }
    }

    @SneakyThrows
    @Override
    public void postPermissions(Integer roleId, List<String> permIds) {
        // 先查询当前 id 是否是 超级管理员，如果是，则拒绝修改权限
        if (roleId == 1)
            throw new Param602Exception("禁止修改超级管理员权限！");
        // 查询 现有id的所有permission
        PermissionExample example = new PermissionExample();
        example.createCriteria().andRoleIdEqualTo(roleId);
        List<Permission> updatePerms = permMapper.selectByExample(example);
        // 遍历现有 permission
        boolean updateFlag = false;
        boolean insertFlag = false;
        for (Permission perm : updatePerms) {
            if (!permIds.remove(perm.getPermission())) {
                // 如果删除成功了，说明包含，不做处理
                //如果删除失败，则不再有该permission，deleted置为true
                updateFlag = true;
                perm.setDeleted(true);
            }
            // 设置更新时间
            perm.setUpdateTime(new Date());
        }
        // permIds中剩下的是需要新插入到 insertList 中的
        List<Permission> insertPerms = new ArrayList<>();
        for (String permId : permIds) {
            insertFlag = true;
            Permission perm = new Permission();
            perm.setRoleId(roleId);
            perm.setAddTime(new Date());
            perm.setUpdateTime(new Date());
            perm.setPermission(permId);
            perm.setDeleted(false);
            insertPerms.add(perm);
        }
        // 插入表，更新表
        if(updateFlag){
            for (Permission updatePerm : updatePerms) {
                permMapper.updateByPrimaryKeySelective(updatePerm);
            }
        }
        if (insertFlag){
            for (Permission insertPerm : insertPerms) {
                permMapper.insertSelective(insertPerm);
            }
        }
    }
}
